package com.golfbox.icbc.controller.notify;

import com.golfbox.icbc.api.BasFaceFaceincrementsynV1Test;
import com.icbc.api.IcbcConstants;
import com.icbc.api.utils.IcbcSignature;
import com.icbc.api.utils.WebUtils;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

public class NotifyTestController {
	private final Logger logger = LoggerFactory.getLogger(NotifyTestController.class);
//	Logger log = log.getLogger(NotifyTestController.class.getName());
	// 验签公钥
	private String APIGW_PUBLIC_KEY = "";
	// 验签私钥
	private String privateKey = "";

	@ResponseBody
	@RequestMapping(value = "/receiveNotify")
	public Object test(HttpServletRequest request) throws Exception {
		logger.info("验签..."); // 通知地址
		boolean verifyFlag = verifySignData(request, "/test/receiveNotify");
		String returnJson;
		if (verifyFlag) {// 验签成功
			logger.info("解密...");
			String bizContent = dencrypt(request);
			logger.info("解密后参数:" + bizContent);// 进行自己的处理,此处默认处理成功，返回通知方成功,return_code=0
			String copReturnCode = "0";// 通知合作方接收成功的返回码，固定
			String copReturnMsg = "success";// 合作方的返回信息，固定
			returnJson = sign(request, copReturnCode, copReturnMsg);
			logger.info("通知响应json结果：{}", returnJson);
			return returnJson;
		} else {// 验签失败
			String copReturnCode = "-12345";
			String copReturnMsg = "icbc jft sign not pass.";
			returnJson = sign(request, copReturnCode, copReturnMsg);
			logger.info("通知响应json结果：{}", returnJson);
		}
		return returnJson;
	}

	/**
	 * 验签方法
	 *
	 * @param request
	 * @param path
	 * @return
	 * @throws Exception
	 */
	private boolean verifySignData(HttpServletRequest request, String path) throws Exception {
		// 网关公钥
		Map<String, String> params = new HashMap<String, String>();
		String api = request.getParameter("api");
		String from = request.getParameter("from");
		String app_id = request.getParameter("app_id");
		String charset = request.getParameter("charset");
		String format = request.getParameter("format");
		String encrypt_type = request.getParameter("encrypt_type");
		String timestamp = request.getParameter("timestamp");
		String biz_content = request.getParameter("biz_content");
		String sign_type = request.getParameter("sign_type");
		String sign = request.getParameter("sign");
		params.put("from", from);
		params.put("api", api);
		params.put("app_id", app_id);
		params.put("charset", charset);
		params.put("format", format);
		params.put("encrypt_type", encrypt_type);
		params.put("timestamp", timestamp);
		params.put("biz_content", biz_content);
		params.put("sign_type", sign_type);// 目前上行网关签名暂时仅支持RSA
		/********** 验证工行上行网关RSA签名 **********/
		String signStr = WebUtils.buildOrderedSignStr(path, params);
		logger.info("验签入参，signStr：[[{}]], sign_type：[[{}]], APIGW_PUBLIC_KEY：[[{}]], charset：[[{}]], sign：[[{}]]",
				signStr, sign_type, APIGW_PUBLIC_KEY, sign);
		boolean flag = IcbcSignature.verify(signStr, sign_type, APIGW_PUBLIC_KEY, charset, sign);
		logger.info("验签结果：[[{}]]", flag);
		return flag;
	}

	/**
	 * 解密
	 *
	 * @param request
	 * @return
	 * @throws IOException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 */
	private String dencrypt(HttpServletRequest request) throws JsonParseException, JsonMappingException, IOException {
		String biz_content = request.getParameter("biz_content");
		String key = "%2B";
		String password = "+";
		String bizContent = biz_content.replaceAll(key, password);
		logger.info("转换上送参数:{}", bizContent);
		// 解析请求数据map
		ObjectMapper mapper = new ObjectMapper();
		Map<String, String> transMap = mapper.readValue(bizContent, Map.class);
		// 获取报文密文信息
		String notifyData = transMap.get("notifyData");
		return new String(Base64.getDecoder().decode(notifyData));
	}

	/**
	 * 加签方法
	 *
	 * @param request
	 * @param copReturnCode
	 * @param copReturnMsg
	 * @return
	 * @throws Exception
	 */
	private String sign(HttpServletRequest request, String copReturnCode, String copReturnMsg) throws Exception {
		String msg_id = new SimpleDateFormat("yyyyMMdd").format(new Date())
				+ new SimpleDateFormat("HHmmss").format(new Date());
		String responseBizContent = "{\"return_code\":\"" + copReturnCode + "\",\"return_msg\":\"" + copReturnMsg + "\""
				+ ",\"msg_id\":\"" + msg_id + "\"}";
		String charset = request.getParameter("charset");// 调用过程使用的编码格式
		/**********
		 * 商户对消息返回响应进行签名，签名方式需与在API平台登记APP的sign_type保持一致(目前基本都是RSA2)
		 **********/
		String signType = IcbcConstants.SIGN_TYPE_RSA2;
		String signStr = "\"response_biz_content\":" + responseBizContent + "," + "\"sign_type\":" + "\"" + signType
				+ "\"";
		String signParam = IcbcSignature.sign(signStr, signType, privateKey, charset);
		String returnJson = "{\"response_biz_content\":" + responseBizContent + ",\"sign_type\":\"" + signType + "\""
				+ ",\"sign\":\"" + signParam + "\"}";
		return returnJson;
	}
}
